﻿// ## 2023/03/01 # 铃 # 新增对敌军科技的判断,新增对恶劣地形的判断,
// ## 2023/02/03 # 铃 # 新城防系统下,出征兵力需要考虑目标城市的耐久度.越坚固的大城市需要派更多兵力
// ## 2021/11/10 # 江东新风 # 加入目标是玩家时，要求兵力数更多 ##
// ## 2021/10/01 # 江东新风 # namespace的韩文改成英文 ##
// ## 2021/09/26 # 江东新风 # 增加影响条件备注 ##
// ## 2020/07/26 ##
namespace AI_ATTACK_TROOPS_MIN_REQUIRED
{
	class Main
	{
		Main()
		{
			pk::set_func(253, pk::func253_t(callback));
		}

		int callback(pk::building @src, pk::building @dst)
		{
			//pk::trace("func_253");
			uint dst_troops = dst.get_available_troops();
			int src_rank = pk::get_scenario().get_ai_table().get_force(src.get_force_id()).troops_rank;
			/*
			根据原始算式，兵力再多也只达到目标据点兵力的2倍，势力越弱，君主性格越大胆，出征兵力就越少。以敌方兵力1000计算
			势力排名百分率(强 <-> 弱)
			君主性格 100     80     60       40     20      2(最小)

			小心	1950	1850	1750	1650	1550	1460
			冷静	1800	1700	1600	1500	1400	1310
			刚胆	1650	1550	1450	1350	1250	1160
			莽撞	1500	1400	1300	1200	1100	1010

			*/
			// 所以君主越小心出兵越多，越莽撞，出兵越少。己方国力排名越强(兵力)，出兵越多，越低，出兵越少。己方国力排名越强

			/********************************************************************************************/
			// 基础值:先计算目标城市的兵力

			int dst_troops_new = 城市8格内同势力兵力(dst) + pk::get_troops(dst);

			/********************************************************************************************/
			// 线性参数:

			//  1.计算君主的性格加成
			int a = pk::get_person(pk::get_kunshu_id(src)).character;
			int b = (3 - a) * 10;

			// 2.势力强弱和出兵的数量逻辑不合理,暂时先不搁置.
			int c = src_rank / 3;

			// 3.目标城市拥有高级城防科技时,增加出兵数
			int t = 0;
			int force_id = dst.get_force_id();
			if (pk::is_valid_force_id(force_id))
			{
				pk::force @force = pk::get_force(force_id);
				if (pk::has_tech(force, 技巧_城壁强化))
					t = 10;
				if (pk::has_tech(force, 技巧_防卫强化))
					t = 30;
			}

			// 4.恶劣地形需要增加出兵数
			int m = 0;
			int path = pk::get_route(src.get_id(), dst.get_id(), src.get_force_id(), true);
			if (path == 路径_一般)
				m = 0;
			else if (path == 路径_海洋 or path == 路径_海)
				m = 30;
			else if (path == 路径_栈道)
			{
				if (src.has_tech(技巧_难所行军))
					m = 30;
				else
					m = 100;
			}
			else
				m = 20;

			// 5.难度和玩家修正
			int k = 0;
			if (pk::get_scenario().difficulty == 难易度_超级 and dst.is_player())
				k = 30;
			else if (pk::get_scenario().difficulty == 难易度_上级 and dst.is_player())
				k = 10;
			else
				k = 0;

			/********************************************************************************************/
			// 非线性参数:

			// 1.城市附近府的兵力.
			int spec_troops = 城市8格内同势力府兵兵力(dst);
			int s = spec_troops;

			// 2.由于新城防系统的城市防御力很高,要增加对目标据点总耐久的考虑.
			auto building_p = ch::get_baseIA(dst.get_id());
			int total_hp = dst.hp + building_p.city_defense;
			int h = total_hp;

			// ********************************* 初始化-把正在攻击的据点放入列表******************************************
			int attacking_troops = 0;
			pk::list<pk::unit @> unit_list = pk::get_unit_list(pk::get_force(src.get_force_id()));
			for (int i = 0; i < unit_list.count; i++)
			{
				pk::unit @unit = unit_list[i];
				if (!pk::is_alive(unit))
					continue;

				//  跳过玩家部队及非普通类型部队
				if (unit.is_player() or unit.type == 部队类型_运输)
					continue;

				if ((unit.order != 部队任务_征服 and unit.order != 部队任务_攻城))
					continue;

				if (!pk::is_valid_base_id(unit.target) or unit.target >= 据点_末)
					continue;

				if (unit.target == dst.get_id())
					attacking_troops += unit.troops;
			}

			int final_troops = pk::max(dst_troops_new, 5000) + pk::max(dst_troops_new, 5000) * (b + m + t + k) / 100 + h * 2 + s - attacking_troops;

			// 如果算出的出兵数大于8万,则按照8万,
			final_troops = pk::clamp(final_troops, pk::max(30000, 50000 - attacking_troops), 80000);
 
			if(dst.get_force_id() == -1 and dst.get_id() < 城市_末)  final_troops = pk::min(final_troops,50000);
			if(dst.get_force_id() == -1 and dst.get_id() >=城市_末)  final_troops = pk::min(final_troops,30000);

			//pk::trace(pk::format("出发城市：{},目标城市:{},b:{},m:{},t:{},k:{},h:{},s:{},attacking_troops :{},final_troops:{}", pk::decode(pk::get_name(src)), pk::decode(pk::get_name(dst)), b, m, t, k, h, s, attacking_troops, final_troops));

			return final_troops;
		}

		int 城市8格内同势力兵力(pk::building @building)
		{
			int enemy_troops = 0;

			int force_id = building.get_force_id();
			if (!pk::is_valid_force_id(force_id))
				return 0;
			pk::force @force = pk::get_force(force_id);
			if (!pk::is_alive(force))
				return 0;
			pk::list<pk::unit @> unit_list = pk::get_unit_list(force);

			for (int i = 0; i < unit_list.count; i++)
			{
				pk::unit @unit0 = unit_list[i];
				if (!pk::is_alive(unit0))
					continue;
				if (unit0.get_force_id() != building.get_force_id())
					continue;
				if (unit0.type != 部队类型_战斗)
					continue;

				if (pk::get_distance(building.get_pos(), unit0.pos) < 8)
					enemy_troops += unit0.troops;
			}
			return enemy_troops;
		}

		int 城市8格内同势力府兵兵力(pk::building @city)
		{
			int spec_troops = 0;
			for (int i = 0; i < ch::get_spec_end(); ++i)
			{
				pk::point pos = ch::get_spec_pos(i);
				pk::building @building = pk::get_building(pos);

				if (!pk::is_alive(building))
					continue;

				if (building.get_force_id() == -1)
					continue;

				pk::force @force = pk::get_force(building.get_force_id());
				if (!pk::is_alive(force))
					continue;

				if (!pk::is_normal_force(building.get_force_id()))
					continue;

				if (building.get_force_id() != city.get_force_id())
					continue;

				if (!pk::is_alive(building))
					continue;

				int spec_id = ch::to_spec_id(building.get_id());
				if (spec_id == -1)
					continue;

				auto spec_t = ch::get_spec_p(i);

				if (pk::get_distance(building.get_pos(), city.get_pos()) < 8)
					spec_troops += spec_t.troops;
			}
			return spec_troops;
		}
	} Main main;
}